Skip to main content

First Play Playback

Overview

First Play stations are trainer-influenced stations whose songs play in a specific order. They can only be played once per unique client, by users accessing from within the United States and its territories. Once a client has heard all the songs in a First Play station, the station may not be played again, so it is important that an application be prepared to play a different station once the client has played through the First Play station.

The recommended way to start playback of a First Play station is with searchForAndSetActiveStation, which finds the station, sets it as the active station, and optionally begins buffering audio in a single network request — see the Station Search recipe for the full API details.

Starting playback of a First Play station

The example below searches for a First Play station named "First Play Station X" and kicks off playback from the first song as soon as audio is buffered:

let queries: [FMStationSearchQuery] = [
.firstPlay(withAdvance: 0, filter: ["name": "First Play Station X"])
]

let player = FMAudioPlayer.shared()

player.search(
forAndSetActiveStation: queries,
searchTimeoutMs: nil, // defaults to 2000ms
prepareToPlay: true,
prepareTimeoutMs: nil // defaults to 5000ms
) { audioItem, error in
if let error {
// no playable station matched the search
print("station search failed: \(error)")
return
}

// "First Play Station X" is now active and audio is buffered
player.play()
}

This works the first time the client plays the station — but remember that a First Play station can only be heard once per client. If the client begins playback of a First Play station with the code above, then listens to part of the station, then makes the call above again, this code will return an error: no query in the search list matches a playable station because the first play station cannot be played again from timestamp 0.

Falling back to a radio station

To keep ensure the client gets music when the first play station is no longer playable, add a second search query that matches an ordinary radio station (or a Replay station). Queries are evaluated in order, so the First Play station is preferred when it is still playable, and the radio station is used otherwise:

let queries: [FMStationSearchQuery] = [
// preferred: the First Play station, if this client can still play it
.firstPlay(withAdvance: 0, filter: ["name": "First Play Station X"]),

// fallback: a plain radio station
.radio(filter: ["name": "Radio Station Y"]),
]

let player = FMAudioPlayer.shared()

player.search(
forAndSetActiveStation: queries,
searchTimeoutMs: nil,
prepareToPlay: true,
prepareTimeoutMs: nil
) { audioItem, error in
if let error {
print("station search failed: \(error)")
return
}

// either "First Play Station X" or "Radio Station Y" is now active
// look at `player.activeStation` if you need to know which
player.play()
}

With this search in place, the active station will be set to "Radio Station Y" and music will be pulled from that station if the client has ever previously played music from "First Play Station X".

Continuing playback of a first play station

If a client kicks off playback of a first play station and quits playback halfway through some song, they may not resume playback from that offset in the station via another searchForAndSetActiveStation call with the 'advance' parameter set to the point they left. The call to searchForAndSetActiveStation will consider that request unsatisfiable and will return the fallback station.